package model.strategys.resolucao;

import model.cubos.Adesivo;
import model.cubos.Cor;
import model.cubos.CuboMagico3x3x3;
import model.rotations.Rotations;

public class ResolveCruz extends Estrategia{
		
	public ResolveCruz(Rotations rotacao) {
		super(rotacao);
	}

	public void resolveCruz(CuboMagico3x3x3 cubo) {

		Adesivo[][][] matriz = cubo.getCubo();
		boolean isFinished = false;

		posicionaAmareloEmCima(cubo, matriz);

		setDestino(matriz[0][1][1]);
		while (!matriz[0][1][1].isCor(Cor.AZUL)) {
			rotacao.girarEixoYSentidoHorario(cubo);
		}

		if (matriz[0][2][1].isCor(Cor.AZUL)
				&& matriz[0][1][1].isCor(Cor.AZUL)
				&& matriz[5][0][1].isCor(Cor.BRANCO)
				&& matriz[5][1][1].isCor(Cor.BRANCO)
				&& (matriz[1][2][1].isCor(Cor.VERMELHO)
						&& matriz[1][1][1].isCor(Cor.VERMELHO)
						&& matriz[5][1][2].isCor(Cor.BRANCO) && matriz[5][1][1]
								.isCor(Cor.BRANCO))
								&& (matriz[2][2][1].isCor(Cor.VERDE)
										&& matriz[2][1][1].isCor(Cor.VERDE)
										&& matriz[5][2][1].isCor(Cor.BRANCO) && matriz[5][1][1]
												.isCor(Cor.BRANCO))
												&& (matriz[3][2][1].isCor(Cor.LARANJA)
														&& matriz[3][1][1].isCor(Cor.LARANJA)
														&& matriz[5][1][0].isCor(Cor.BRANCO) && matriz[5][1][1]
																.isCor(Cor.BRANCO))) {
			return;
		}

		while (!isFinished) {
			if (matriz[0][0][1].isCor(Cor.BRANCO)
					|| matriz[1][0][1].isCor(Cor.BRANCO)
					|| matriz[2][0][1].isCor(Cor.BRANCO)
					|| matriz[3][0][1].isCor(Cor.BRANCO)) {

				etapa3(cubo, matriz);
			} else if (matriz[0][1][0].isCor(Cor.BRANCO)
					|| matriz[1][1][0].isCor(Cor.BRANCO)
					|| matriz[2][1][0].isCor(Cor.BRANCO)
					|| matriz[3][1][0].isCor(Cor.BRANCO)) {

				etapa4(cubo, matriz);
			} else if (matriz[0][1][2].isCor(Cor.BRANCO)
					|| matriz[1][1][2].isCor(Cor.BRANCO)
					|| matriz[2][1][2].isCor(Cor.BRANCO)
					|| matriz[3][1][2].isCor(Cor.BRANCO)) {

				etapa5(cubo, matriz);
			}

			else if (matriz[5][0][1].isCor(Cor.BRANCO)
					|| matriz[5][1][0].isCor(Cor.BRANCO)
					|| matriz[5][1][2].isCor(Cor.BRANCO)
					|| matriz[5][2][1].isCor(Cor.BRANCO)) {

				etapa7(cubo, matriz);

			} else if (matriz[0][2][1].isCor(Cor.BRANCO)
					|| matriz[1][2][1].isCor(Cor.BRANCO)
					|| matriz[2][2][1].isCor(Cor.BRANCO)
					|| matriz[3][2][1].isCor(Cor.BRANCO)) {

				etapa8(cubo, matriz);
			}

			if ((matriz[4][0][1].isCor(Cor.BRANCO))
					&& (matriz[4][1][0].isCor(Cor.BRANCO))
					&& (matriz[4][1][2].isCor(Cor.BRANCO))
					&& (matriz[4][2][1].isCor(Cor.BRANCO))) {

				etapa9(cubo, matriz);
			}
			setDestino(matriz[0][1][1]);

			while (!matriz[0][1][1].isCor(Cor.AZUL)) {
				rotacao.girarEixoYSentidoHorario(cubo);
			}

			if ((matriz[0][2][1].isCor(Cor.AZUL)
					&& matriz[0][1][1].isCor(Cor.AZUL)
					&& matriz[5][0][1].isCor(Cor.BRANCO) && matriz[5][1][1]
							.isCor(Cor.BRANCO))
							&& (matriz[1][2][1].isCor(Cor.VERMELHO)
									&& matriz[1][1][1].isCor(Cor.VERMELHO)
									&& matriz[5][1][2].isCor(Cor.BRANCO) && matriz[5][1][1]
											.isCor(Cor.BRANCO))
											&& (matriz[2][2][1].isCor(Cor.VERDE)
													&& matriz[2][1][1].isCor(Cor.VERDE)
													&& matriz[5][2][1].isCor(Cor.BRANCO) && matriz[5][1][1]
															.isCor(Cor.BRANCO))
															&& (matriz[3][2][1].isCor(Cor.LARANJA)
																	&& matriz[3][1][1].isCor(Cor.LARANJA)
																	&& matriz[5][1][0].isCor(Cor.BRANCO) && matriz[5][1][1]
																			.isCor(Cor.BRANCO))) {

				isFinished = true;
			}

		}
	}
	
	public void posicionaAmareloEmCima(CuboMagico3x3x3 cubo, Adesivo[][][] matriz) {

		setDestino(matriz[CuboMagico3x3x3.FACE_SUPERIOR][1][1]);
		
		while (!matriz[CuboMagico3x3x3.FACE_SUPERIOR][1][1].isCor(Cor.AMARELO)) {
			if (matriz[1][1][1].isCor(Cor.AMARELO)
					|| matriz[5][1][1].isCor(Cor.AMARELO)
					|| matriz[3][1][1].isCor(Cor.AMARELO)) {
				rotacao.girarEixoZSentidoHorario(cubo);
			}
			if (matriz[0][1][1].isCor(Cor.AMARELO)
					|| matriz[2][1][1].isCor(Cor.AMARELO)) {
				rotacao.girarEixoXSentidoHorario(cubo);
			}
		}

	}
	
	private void etapa3(CuboMagico3x3x3 cubo, Adesivo[][][] matriz) {
		setDestino(matriz[0][0][1]);

		while (!matriz[0][0][1].isCor(Cor.BRANCO)) {
			rotacao.girarCimaSentidoHorario(cubo);
		}

		setDestino(matriz[0][1][2]);
		rotacao.girarFrenteSentidoHorario(cubo);
		setDestino(matriz[4][1][2]);

		while (matriz[4][1][2].isCor(Cor.BRANCO)) {
			rotacao.girarCimaSentidoHorario(cubo);
		}

		setDestino(matriz[4][1][2]);
		rotacao.girarDireitaSentidoHorario(cubo);
	}
	
	private void etapa4(CuboMagico3x3x3 cubo, Adesivo[][][] matriz) {
		setDestino(matriz[0][1][0]);

		while (!matriz[0][1][0].isCor(Cor.BRANCO)) {
			rotacao.girarEixoYSentidoHorario(cubo);
		}

		setDestino(matriz[4][1][0]);

		while (matriz[4][1][0].isCor(Cor.BRANCO)) {
			rotacao.girarCimaSentidoHorario(cubo);
		}

		setDestino(matriz[4][1][0]);

		rotacao.girarEsquerdaSentidoAntiHorario(cubo);
	}

	private void etapa5(CuboMagico3x3x3 cubo, Adesivo[][][] matriz) {
		setDestino(matriz[3][1][2]);
		while (!matriz[3][1][2].isCor(Cor.BRANCO)) {
			rotacao.girarEixoYSentidoHorario(cubo);
		}

		if (matriz[4][2][1].isCor(Cor.BRANCO)) {
			setDestino(matriz[4][2][1]);
			while (matriz[4][2][1].isCor(Cor.BRANCO)) {
				rotacao.girarCimaSentidoHorario(cubo);
			}
		}
		setDestino(matriz[4][2][1]);

		rotacao.girarFrenteSentidoHorario(cubo);
	}

	private void etapa7(CuboMagico3x3x3 cubo, Adesivo[][][] matriz) {
		setDestino(matriz[5][0][1]);

		while (!matriz[5][0][1].isCor(Cor.BRANCO)) {
			rotacao.girarBaseSentidoHorario(cubo);
		}

		if (matriz[4][2][1].isCor(Cor.BRANCO)) {
			setDestino(matriz[4][2][1]);

			while (matriz[4][2][1].isCor(Cor.BRANCO)) {
				rotacao.girarCimaSentidoHorario(cubo);
			}

		}

		setDestino(matriz[4][2][1]);
		rotacao.girarFrenteSentidoHorario(cubo);
		rotacao.girarFrenteSentidoHorario(cubo);
	}

	private void etapa8(CuboMagico3x3x3 cubo, Adesivo[][][] matriz) {
		setDestino(matriz[0][2][1]);

		while (!matriz[0][2][1].isCor(Cor.BRANCO)) {
			rotacao.girarBaseSentidoHorario(cubo);
		}

		setDestino(matriz[4][2][1]);

		while (matriz[4][2][1].isCor(Cor.BRANCO)) {
			rotacao.girarCimaSentidoHorario(cubo);
		}

		rotacao.girarFrenteSentidoHorario(cubo);
	}
	
	private void etapa9(CuboMagico3x3x3 cubo, Adesivo[][][] matriz) {
		for (int j = 0; j < 4; j++) {
			setDestino(matriz[0][1][1]);

			switch (matriz[0][1][1].getKey()) {
			case 4:
				etapa9Rotations(cubo, matriz, Cor.AZUL);
				break;

			case 13:
				etapa9Rotations(cubo, matriz, Cor.VERMELHO);
				break;

			case 22:
				etapa9Rotations(cubo, matriz, Cor.VERDE);
				break;

			case 31:
				etapa9Rotations(cubo, matriz, Cor.LARANJA);
				break;
			}
			rotacao.girarEixoYSentidoHorario(cubo);
		}
	}
	
	private void etapa9Rotations(CuboMagico3x3x3 cubo, Adesivo[][][] matriz,
			model.cubos.Cor corAtual) {
		while (!(matriz[0][0][1].isCor(corAtual) && matriz[4][2][1]
				.isCor(Cor.BRANCO))) {
			rotacao.girarCimaSentidoHorario(cubo);
		}
		rotacao.girarFrenteSentidoHorario(cubo);
		rotacao.girarFrenteSentidoHorario(cubo);
	}
	
}
